package org.imdm.portal.loadchecker.telnet;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

public class MDMLoadChecker {

	private static final String HOSTS = "hosts.ini";
	private static final String RESULTS = "load.data";

	private static final String STANDALONE_MODE = "standalone";
	private static final String STANDALONE_MODE_WITH_SIMPLE_OUTPUT = "simpleoutput";
	private static final String DAEMON_MODE = "daemon";

	private Map hostVersion = new HashMap();
	private Map hostClient = new HashMap();

	public static void main(String[] args){
		System.out.println("Running MDMLoadChecker ...");
		if (args.length < 2) {
		    System.err.println("Usage:  java MDMLoaderChecker " +
	                               "username password.\n");
		    System.exit(1);
		}

		String username = args[0];
		String password = args[1];
		String mode = args.length<3? null : args[2];


		List hosts = new HostConfig(new File(HOSTS)).getHosts();

		new MDMLoadChecker().check(username,password,mode);


	}

	public void check(String username, String password,String daemon){
		List hosts = new HostConfig(new File(HOSTS)).getHosts();


		if(daemon!=null&&daemon.equals(STANDALONE_MODE_WITH_SIMPLE_OUTPUT)){
			checkWithSimpleOutput(hosts,username,password);

		}else if(daemon!=null&&daemon.equals(DAEMON_MODE)){
			checkWithDaemonRunning(username,password);

		}else{
			check(hosts,username,password);
		}
	}

	public void writeToFile(List hosts){

	    FileOutputStream fos = null;
	    try {
			fos = new FileOutputStream(RESULTS);

			BufferedWriter awriter;
	        awriter = new BufferedWriter(new OutputStreamWriter(fos, "8859_1"));

	        writeln(awriter, "#" + new Date().toString());

		    for(int i =0;i<hosts.size();i++){
		    	MDMServerInfo info = (MDMServerInfo)hostVersion.get(hosts.get(i));
		    	String version = "N/A";
		    	String currentUser = "N/A";
		    	String userNumber = "N/A";
		    	if(info!=null){
		    		version = info.getVersion();
		    		currentUser = info.getCurrentUser();
		    		userNumber = info.getCurrentUserNumber();
		    	}
		    	writeln(awriter,hosts.get(i)+" "+version+" "+currentUser+" "+userNumber);
		    }
	        awriter.flush();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally{
			if(fos!=null){
				try {
					fos.close();
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}

    private static void writeln(BufferedWriter bw, String s) throws IOException {
        bw.write(s);
        bw.newLine();
    }

    private void checkWithDaemonRunning(String username,String password){
		List threads = new ArrayList();

		while(true){
			List hosts = new HostConfig(new File(HOSTS)).getHosts();
			startThread(threads,hosts,username,password);
			threads.clear();

		    writeToFile(hosts);
		    try {
				Thread.sleep(1000*5);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
    }

	public void startThread(List threads, List hosts, String username, String password){

		for(int i =0;i<hosts.size();i++){
			ReadVersion readVersion = new ReadVersion((String)hosts.get(i),getTelnetClient((String)hosts.get(i),username,password));
			readVersion.start();
			threads.add(readVersion);
		}

		for(int i=0;i<threads.size();i++){
			try {
				((Thread)threads.get(i)).join();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}


	}

	public void checkWithSimpleOutput(List hosts,String username, String password){
		List threads = new ArrayList();
	    startThread(threads,hosts,username,password);

		for(int i=0;i<threads.size();i++){
				((ReadVersion)threads.get(i)).disconnect();
		}

	    for(int i =0;i<hosts.size();i++){
	    	MDMServerInfo info = (MDMServerInfo)hostVersion.get(hosts.get(i));
	    	String version = "N/A";
	    	String currentUser = "N/A";
	    	String userNumber = "N/A";
	    	if(info!=null){
	    		version = info.getVersion();
	    		currentUser = info.getCurrentUser();
	    		userNumber = info.getCurrentUserNumber();
	    	}
	    	System.out.println(hosts.get(i)+" "+version+" "+currentUser+" "+userNumber);
	    }

	    writeToFile(hosts);

	}

	public void check(List hosts,String username, String password){
		List threads = new ArrayList();
		startThread(threads,hosts,username,password);

		for(int i=0;i<threads.size();i++){
				((ReadVersion)threads.get(i)).disconnect();
		}


		System.out.print("**********************************");
		System.out.println("********************************");
		System.out.print("  If the tool can't get the ");
		System.out.println("version information, please check");
		System.out.println("  the server manually.      ");
	    System.out.print("**********************************");
	    System.out.println("********************************");
	    System.out.println("Server \t\t Version \t Current User \t Login Users\n");
	    for(int i =0;i<hosts.size();i++){
	    	MDMServerInfo info = (MDMServerInfo)hostVersion.get(hosts.get(i));
	    	String version = "N/A";
	    	String currentUser = "N/A";
	    	String userNumber = "N/A";
	    	if(info!=null){
	    		version = info.getVersion();
	    		currentUser = info.getCurrentUser();
	    		userNumber = info.getCurrentUserNumber();
	    	}
	    	System.out.println(hosts.get(i)+" \t "+version+" \t "+currentUser+" \t "+userNumber);
	    }

	    System.out.print("**********************************");
	    System.out.println("********************************");
	}

	private synchronized TelnetClientAdvance getTelnetClient(String host,String username,String password){
		if(hostClient.get(host)==null){
			TelnetClientAdvance telnet = new TelnetClientAdvance();
			telnet.setServer(host);
			telnet.setUser(username);
			telnet.setPassword(password);
			hostClient.put(host,telnet);
		}
		return (TelnetClientAdvance)hostClient.get(host);
	}

	class MDMServerInfo{
		private String version;
		private String currentUser;
		private String currentUserNumber;
		public String getCurrentUser() {
			return currentUser;
		}
		public void setCurrentUser(String currentUser) {
			this.currentUser = currentUser;
		}
		public String getCurrentUserNumber() {
			return currentUserNumber;
		}
		public void setCurrentUserNumber(String currentUserNumber) {
			this.currentUserNumber = currentUserNumber;
		}
		public String getVersion() {
			return version;
		}
		public void setVersion(String version) {
			this.version = version;
		}
	}

	class ReadVersion extends Thread{

		private Command command;
		private Command userNumberCommand;
		private Command currentUserCommand;
		private String host;

		public ReadVersion(String host,TelnetClientAdvance telnet){
			this.host = host;
			command = new ReadVersionCommand(telnet);
			userNumberCommand = new WhoCommand(telnet);
			currentUserCommand = new ReadUserCommand(telnet);
		}
		public void run(){
			try {
				MDMServerInfo info = new MDMServerInfo();
				info.setVersion(command.execute());
				info.setCurrentUser(currentUserCommand.execute());
				info.setCurrentUserNumber(userNumberCommand.execute());
				hostVersion.put(host,info);
				System.out.println("---" + host + "--- checked");
			} catch (TelnetException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}


		public void disconnect(){
			//one command stop is enough for all the other command which execute on
			//the same server
			command.stop();
		}
	}

}


